package com.yuma.tingshu.album.listener;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import com.yuma.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.yuma.tingshu.album.service.AlbumInfoService;
import com.yuma.tingshu.common.constant.RedisConstant;
import com.yuma.tingshu.common.util.MxwObject;
import com.yuma.tingshu.model.album.AlbumAttributeValue;
import com.yuma.tingshu.model.album.AlbumInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class MxwListener {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AlbumAttributeValueMapper attributeValueMapper;

    @RabbitListener(queues = "mxw.test.queue")
    public void mxwListen(String jsonMxwObject, Channel channel, Message message) throws IOException {
        // 1.对象判空
        if (jsonMxwObject == null) {
            // 应答
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        // 2.非空转MxwObject
        MxwObject mxwObject = JSON.parseObject(jsonMxwObject, MxwObject.class);
        if (mxwObject == null) {
            // 应答
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        // 3.幂等性
        if (!redisTemplate.opsForValue().setIfAbsent(String.valueOf(mxwObject.getXid()), "", RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS)) {
            // 应答
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        // 此try中如果一旦发生mysql操作异常，可以重新入队再次消费
        try {
            // 操作数据库查询可能需要使用到，redis的操作
            //1.判断库
            if ("tingshu_album".equals(mxwObject.getDatabase())) {
                //2.判断表
                if ("album_info".equals(mxwObject.getTable())) {
                    //3.判断操作 insert,update,delete -> 同步到redis中
                    if ("insert".equals(mxwObject.getType()) || "update".equals(mxwObject.getType())) {
                        //1.把mxwObject的data字段转成AlbumInfo,重新根据id查询
                        AlbumInfo albumInfo = JSON.parseObject(mxwObject.getData(), AlbumInfo.class);
                        //2.重新查询属性标签
                        List<AlbumAttributeValue> albumAttributeValues = attributeValueMapper.selectList(
                                new LambdaQueryWrapper<AlbumAttributeValue>()
                                        .eq(AlbumAttributeValue::getAlbumId, albumInfo.getId()));
                        albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);
                        //3.写入redis
                        redisTemplate.opsForValue().set(RedisConstant.ALBUM_INFO_PREFIX + albumInfo.getId(),
                                albumInfo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS);
                    } else if ("delete".equals(mxwObject.getType())) {
                        redisTemplate.delete(RedisConstant.ALBUM_INFO_PREFIX + mxwObject.getData());
                    }
                }
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            // 如果已经重复投递还失败直接拒绝掉，不再进行重试
            if (message.getMessageProperties().getRedelivered()) {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
            // 如果第一次操作抛出异常，则重新入队，删除幂等性key，以方便重试
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
            redisTemplate.delete(String.valueOf(mxwObject.getXid()));
            e.printStackTrace();
        }
    }
}